package com.ayf.payment.game.api.controller.paychannel;

import com.ayf.payment.game.api.config.SystemInitialization;
import com.ayf.payment.game.api.service.MerchantPayOrderService;
import com.ayf.payment.game.api.service.OrderService;
import com.ayf.payment.game.api.service.platform.MerchantCashOutService;
import com.ayf.payment.game.api.service.platform.SubstitutePayConfigService;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import com.swwx.charm.zookeeper.exception.GetLockFailedException;
import com.swwx.charm.zookeeper.exception.ReleaseLockFailedException;
import com.swwx.charm.zookeeper.lock.DistributedLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author ad
 * @Title: BasePayNotifyController
 * @Copyright: Copyright (c) 2020
 * @Description: <br>
 * @Company: a.com
 * @Created on 2020/7/310:31
 */
@Component
public abstract class BasePayNotifyController {
    @Autowired
    protected DistributedLock distributedLock;
    @Autowired
    protected OrderService orderService;
    @Autowired
    protected SystemInitialization systemInitialization;

    @Autowired
    protected MerchantPayOrderService merchantPayOrderService;
    @Autowired
    protected MerchantCashOutService merchantCashOutService;
    @Autowired
    protected SubstitutePayConfigService substitutePayConfigService;

    // 交易通知异步业务处理
    protected abstract void notifyAsyncBusinesExec(HttpServletRequest request,HttpServletResponse response,Object obj);
    // 交易通知同步业务处理
    protected abstract void notifySyncBusinesExec(HttpServletRequest request,HttpServletResponse response);

    // 代付通知异步业务处理
    protected abstract void agentPayNotifyAsyncBusinesExec(HttpServletRequest request, HttpServletResponse response, Object obj);

    protected void notifyAsync(HttpServletRequest request,HttpServletResponse response,String orderNo){
        notifyAsync(request,response,orderNo,null);
    }

    protected void notifyAsync(HttpServletRequest request,HttpServletResponse response,String orderNo,Object obj){
        boolean lock = false;
        String traceId = SnowFlakeUtils.getTraceId().concat(" ").concat(orderNo);
        String lockName = this.getClass().getSimpleName().concat(System.getenv("XY_GAME_PAY_LOCK_FLAG")).concat(orderNo).concat("notifyAsync");
        try {
            if (lock = distributedLock.getLock(lockName)) {
                notifyAsyncBusinesExec(request,response,obj);
            }
        } catch (GetLockFailedException e) {
            LogPortal.error("{} >>> [DISTRIBUTED_LOCK_ACQUIRE_FAILED_ZK] 分布式锁获取失败,锁名称为:{}", traceId, lockName);
            LogPortal.error("{} >>> {} 获取lock失败", e, traceId, lockName);
        } catch (Exception e) {
            LogPortal.error("{} >>> {} 任务执行出错 ", e, traceId, lockName);
        } finally {
            if (lock) {
                LogPortal.info(traceId + " >>> " + lockName + " finished.");
                try {
                    distributedLock.releaseLock(lockName);
                } catch (ReleaseLockFailedException e) {
                    LogPortal.error("{} >>> [DISTRIBUTED_LOCK_RELEASE_FAILED_ZK] 分布式锁释放失败,锁名称为:{}", traceId, lockName);
                    LogPortal.error("{} >>> {} 释放失败", e, traceId, lockName);
                }
            }
        }
    }

    protected void notifySync(HttpServletRequest request,HttpServletResponse response,String orderNo){
        boolean lock = false;
        String traceId = SnowFlakeUtils.getTraceId().concat(" ").concat(orderNo);
        String lockName = this.getClass().getSimpleName().concat(System.getenv("XY_GAME_PAY_LOCK_FLAG")).concat(orderNo).concat("notifySync");
        try {
            if (lock = distributedLock.getLock(lockName)) {
                notifySyncBusinesExec(request,response);
            }
        } catch (GetLockFailedException e) {
            LogPortal.error("{} >>> [DISTRIBUTED_LOCK_ACQUIRE_FAILED_ZK] 分布式锁获取失败,锁名称为:{}", traceId, lockName);
            LogPortal.error("{} >>> {} 获取lock失败", e, traceId, lockName);
        } catch (Exception e) {
            LogPortal.error("{} >>> {} 任务执行出错 ", e, traceId, lockName);
        } finally {
            if (lock) {
                LogPortal.info(traceId + " >>> " + lockName + " finished.");
                try {
                    distributedLock.releaseLock(lockName);
                } catch (ReleaseLockFailedException e) {
                    LogPortal.error("{} >>> [DISTRIBUTED_LOCK_RELEASE_FAILED_ZK] 分布式锁释放失败,锁名称为:{}", traceId, lockName);
                    LogPortal.error("{} >>> {} 释放失败", e, traceId, lockName);
                }
            }
        }
    }

    protected void agentPayNotifyAsync(HttpServletRequest request,HttpServletResponse response,String orderNo){
        agentPayNotifyAsync(request,response,orderNo,null);
    }

    protected void agentPayNotifyAsync(HttpServletRequest request,HttpServletResponse response,String orderNo,Object obj){
        boolean lock = false;
        String traceId = SnowFlakeUtils.getTraceId().concat(" ").concat(orderNo);
        String lockName = this.getClass().getSimpleName().concat(System.getenv("XY_GAME_PAY_LOCK_FLAG")).concat(orderNo).concat("agentPayNotifyAsync");
        try {
            if (lock = distributedLock.getLock(lockName)) {
                agentPayNotifyAsyncBusinesExec(request,response,obj);
            }
        } catch (GetLockFailedException e) {
            LogPortal.error("{} >>> [DISTRIBUTED_LOCK_ACQUIRE_FAILED_ZK] 分布式锁获取失败,锁名称为:{}", traceId, lockName);
            LogPortal.error("{} >>> {} 获取lock失败", e, traceId, lockName);
        } catch (Exception e) {
            LogPortal.error("{} >>> {} 任务执行出错 ", e, traceId, lockName);
        } finally {
            if (lock) {
                LogPortal.info(traceId + " >>> " + lockName + " finished.");
                try {
                    distributedLock.releaseLock(lockName);
                } catch (ReleaseLockFailedException e) {
                    LogPortal.error("{} >>> [DISTRIBUTED_LOCK_RELEASE_FAILED_ZK] 分布式锁释放失败,锁名称为:{}", traceId, lockName);
                    LogPortal.error("{} >>> {} 释放失败", e, traceId, lockName);
                }
            }
        }
    }
}
